package com.piece.core.framework.util.net;

import com.piece.core.framework.util.collection.ArrayUtil;
import com.piece.core.framework.util.string.StringUtil;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

/**
 * Peer工具
 */
public class PeerUtil {

    private PeerUtil() {
        throw new IllegalStateException("对象禁止实例化");
    }

    /**
     * IP和端口占用字节大小
     */
    private static final int IP_PORT_LENGTH = 6;

    private static final int ALLOWED_FAST_MASK = 0xFFFFFF00;

    private static final int ALLOWED_FAST_K = 10;

    /**
     * 读取IP和端口
     */
    public static final Map<String, Integer> read(byte[] bytes) {
        if (null == bytes) {
            return null;
        }
        final ByteBuffer buffer = ByteBuffer.wrap(bytes);
        return read(buffer);
    }

    /**
     * 读取IP和端口
     */
    public static final Map<String, Integer> read(ByteBuffer buffer) {
        if (null == buffer) {
            return null;
        }
        final Map<String, Integer> data = new HashMap<>();
        while (buffer.remaining() >= IP_PORT_LENGTH) {
            final String ip = IpUtil.decodeIntToIp(buffer.getInt());
            final int port = IpUtil.decodePort(buffer.getShort());
            data.put(ip, port);
        }
        return data;
    }

    /**
     * 计算快速允许Piece索引
     * <p>协议链接：http://www.bittorrent.org/beps/bep_0006.html</p>
     *
     * @param pieceSize Piece数量：种子Piece总量
     * @param ipAddress IP地址：Peer地址
     * @param infoHash  InfoHash
     */
    public static final int[] allowedFast(int pieceSize, String ipAddress, byte[] infoHash) {
        final int ipValue = IpUtil.encodeIpToInt(ipAddress);
        ByteBuffer buffer = ByteBuffer.allocate(24); // IP(4) + InfoHash(20)
        buffer.putInt(ALLOWED_FAST_MASK & ipValue);
        buffer.put(infoHash);
        int size = 0;
        final int[] seqs = new int[ALLOWED_FAST_K];
        while (size < ALLOWED_FAST_K) {
            buffer = ByteBuffer.wrap(StringUtil.sha1(buffer.array()));
            for (int index = 0; index < 5 && size < ALLOWED_FAST_K; index++) {
                final int seq = (int) (Integer.toUnsignedLong(buffer.getInt()) % pieceSize);
                if (ArrayUtil.indexOf(seqs, 0, size, seq) == -1) {
                    seqs[size++] = seq;
                }
            }
        }
        return seqs;
    }

    /**
     * HTTP传输编码（PeerId、InfoHash）
     *
     * @param hex PeerId、InfoHash
     */
    public static final String urlEncode(String hex) {
        int index = 0;
        final int length = hex.length();
        final StringBuilder builder = new StringBuilder();
        do {
            builder.append("%").append(hex.substring(index, index + 2));
            index += 2;
        } while (index < length);
        return builder.toString();
    }

    /**
     * HTTP传输编码（PeerId、InfoHash）
     * <p>不用编码字符：0-9、a-z、A-Z、'.'、'-'、'_'、'~'</p>
     * <p>协议链接：https://wiki.theory.org/index.php/BitTorrentSpecification#Tracker_HTTP.2FHTTPS_Protocol</p>
     *
     * @param bytes PeerId、InfoHash
     */
    public static final String urlEncode(byte[] bytes) {
        char value;
        String valueHex;
        final StringBuilder builder = new StringBuilder();
        for (int index = 0; index < bytes.length; index++) {
            value = (char) bytes[index];
            if ((value >= '0' && value <= '9') ||
                            (value >= 'a' && value <= 'z') ||
                            (value >= 'A' && value <= 'Z') ||
                            value == '.' ||
                            value == '-' ||
                            value == '_' ||
                            value == '~') {
                builder.append(value);
            } else {
                valueHex = Integer.toHexString(value & 0xFF);
                builder.append("%");
                if (valueHex.length() < 2) {
                    builder.append("0");
                }
                builder.append(valueHex);
            }
        }
        return builder.toString();
    }
}
